#include "stdafx.h"
#include "Buffer.h"
#include "fileio.h"
#include "win32exception.h"

// 10 megs of buffer
const DWORD c_bufferlength = 10 * 1024 * 1024;

Buffer::Buffer()
{
	m_offset = 0;
	m_length = 0;
	m_bufferlength = c_bufferlength;
	m_buffer = new BYTE[m_bufferlength];
}

Buffer::~Buffer()
{
	delete [] m_buffer;
	m_buffer = nullptr;
}

bool Buffer::Read(const std::wstring & filename)
{
	//
	// update members to account for prior operation
	//
	m_offset = m_offset + m_length;
	m_length = m_bufferlength;

	printf("%S reading at offset: %lld bytes: %ld\r\n", filename.c_str(), m_offset, m_length);

	BOOL fRet = FALSE;
	DWORD dwLastError = 0;

	HANDLE hFile = FileIO::OpenFileRead(filename);

	LARGE_INTEGER liOffset;
	if (m_offset > LLONG_MAX)
	{
		throw std::exception("can't seek that far");
	}

	liOffset.QuadPart = m_offset;

	fRet = SetFilePointerEx(hFile, liOffset, NULL, FILE_BEGIN);
	if (!fRet)
	{
		dwLastError = GetLastError();
		throw Win32Exception("can't set file pointer for read", dwLastError);
	}

	DWORD dwBytesRead = 0;

	fRet = ReadFile(hFile, m_buffer, m_bufferlength, &dwBytesRead, NULL);
	if (!fRet)
	{
		dwLastError = GetLastError();
		throw Win32Exception("can't read file data", dwLastError);
	}
	
	FileIO::CloseFile(&hFile);

	m_length = dwBytesRead;

	if (0 == dwBytesRead)
	{
		// no more data to read
		return false;
	}

	return true;
}

void Buffer::Write(const std::wstring & filename)
{
	printf("%S writing at offset: %lld bytes: %ld\r\n", filename.c_str(), m_offset, m_length);

	BOOL fRet = FALSE;
	DWORD dwLastError = 0;

	HANDLE hFile = FileIO::OpenFileWrite(filename);

	if (m_offset > LLONG_MAX)
	{
		throw std::exception("how did read succeed??");
	}

	LARGE_INTEGER liOffset;
	liOffset.QuadPart = m_offset;

	fRet = SetFilePointerEx(hFile, liOffset, NULL, FILE_BEGIN);
	if (!fRet)
	{
		dwLastError = GetLastError();
		throw Win32Exception("can't set file pointer for read", dwLastError);
	}

	DWORD dwBytesWritten = 0;

	fRet = WriteFile(hFile, m_buffer, m_length, &dwBytesWritten, NULL);
	if (!fRet)
	{
		dwLastError = GetLastError();
		throw Win32Exception("can't read file data", dwLastError);
	}

	if (dwBytesWritten != m_length)
	{
		throw std::exception("writefile success, but didn't write all the bytes??");
	}

	FileIO::CloseFile(&hFile);
}

ULONGLONG Buffer::begin()
{
	return m_offset;
}

ULONGLONG Buffer::size()
{
	return m_length;
}
